# -*- coding: utf-8 -*-

import time
from openerp import netsvc
from openerp.osv import osv,fields
from openerp.addons.sale import sale
from openerp.addons.base.res import res_currency
from openerp.addons import warning
from openerp.tools.translate import _
import openerp.addons.decimal_precision as dp
from openerp.addons.sale_margin import sale_margin
from openerp.workflow.wkf_service import workflow_service
class sale_order(osv.osv):
    _inherit = 'sale.order'
    _order = 'write_date desc'
    def _sum_other_cost(self, cr, uid, ids, field_name, arg, context=None):
        res = {}
        for order in self.browse(cr, uid, ids, context=context):
            val = 0.0
            for line in order.cost_line:
                val += line.local_cost
            res[order.id] = val
        return res
    def _product_margin_line(self, cr, uid, id, context=None):
        line = self.pool.get('sale.order.line').browse(cr, uid, id, context=context)
        line_margin = 0
        if line.product_id:
            if line.purchase_price:
                line_margin = round((line.price_unit*line.product_uos_qty*(100.0-line.discount)/100.0) -(line.purchase_price*line.product_uos_qty), 2)
            else:
                line_margin = round((line.price_unit*line.product_uos_qty*(100.0-line.discount)/100.0) -(line.product_id.standard_price*line.product_uos_qty), 2)
        return line_margin    
    def _product_margin(self, cr, uid, ids, field_name, arg, context=None):
        result = {}
        for sale in self.browse(cr, uid, ids, context=context):
            result[sale.id] = 0.0
            for line in sale.order_line:
                result[sale.id] += self._product_margin_line(cr,uid,line.id,context=context)
        return result    
    def _get_margin_new(self, cr, uid, ids, field_name, arg, context=None):
        res = {}
        other_cost_total = self._sum_other_cost(cr, uid, ids, field_name, arg)
#        margin = self._product_margin(cr, uid, ids, field_name, arg)
        print self._product_margin
        margin = self._product_margin(cr, uid, ids, field_name, arg)
        cur_obj = self.pool.get('res.currency')
        for order in self.browse(cr, uid, ids, context=context):
            margin_local_curr = 0
            if(margin[order.id] != 0):
                if order.curr_rate_quote and order.curr_rate_quote > 0:
                    margin_local_curr = margin[order.id]/order.curr_rate_quote
                else:
                    margin_local_curr = cur_obj.compute(cr,uid,order.currency_id.id,\
                                                        order.company_id.currency_id.id,margin[order.id])
            res[order.id] = margin_local_curr - other_cost_total[order.id] + order.pur_ret_tax_eval
        return res
    
    def _calc_ret_tax_eval(self, cr, uid, ids, field_name, arg, context=None):
        res = {}
        order_po = None
        order_po_line = None
        for order in self.browse(cr, uid, ids, context=context):
            res[order.id] = 0.0
            #正式报关后才计算退税
            if not order.is_normal_export: continue
            #循环销售订单明细,检查相关采购单
            for line in order.order_line:
                if(not line.po_line_id or len(line.po_line_id) <= 0): continue
                order_po = line.po_name
                #采购单没开票不计算退税
                if not order_po.has_pur_invoice: continue
                #purchase paper tax rate
                pur_paper_rate = (order_po.partner_id.pur_inv_paper_rate or 0.0)/100.0
                order_po_line = line.po_line_id[0]
                #return tax rate
                ret_tax_rate = (order_po_line.product_id.ret_tax_rate or 0.0)/100.0
                #return tax quantity
                order_qty = line.product_uom_qty
                if order_qty > order_po_line.product_qty: order_qty =  order_po_line.product_qty
                #purchase line subtotal
                line_amount = order_po_line.price_unit * order_qty
                res[order.id] += (line_amount/(1 + pur_paper_rate)) * ret_tax_rate
        return res
    
    def _get_order_line(self, cr, uid, ids, context=None):
        result = {}
        for line in self.pool.get('sale.order.line').browse(cr, uid, ids, context=context):
            result[line.order_id.id] = True
        return result.keys()  
    
    def _get_order_cost_line(self, cr, uid, ids, context=None):
        result = {}
        for line in self.pool.get('sale.order.cost').browse(cr, uid, ids, context=context):
            result[line.order_id.id] = True
        return result.keys()
    
    _columns = {
        'ship_method': fields.selection([('air','By Airlines'),
                                         ('ocean','By Ocean'),
                                         ('inter_express','By international express offering door to door service'),
                                         ('to_be_arranged','To Be Arranged'),], "Ship Method"),
        'load_port': fields.char("Loading Port",size=64),
        'discharge_port': fields.char('Discharge Port',size=64),
        'freight_pay_method': fields.many2many('option.list', 'sale_freight_pay',id1='order_id', id2='freight_pay_id', string='Freight Pay', 
                                           domain=[('option_name','=','freight_pay_method')]),                                           
        'res_pay_account_id': fields.many2one('res.pay.account','Means of Payment'),
         'curr_rate_quote': fields.float('报价日汇率',digits=(12,6)),
         'curr_rate_confirm': fields.float('确认销售日汇率',digits=(12,6)),
         'curr_rate_pay': fields.float('收款日汇率',digits=(12,6)),
         'curr_rate_finish': fields.float('结汇汇率',digits=(12,6)),
                         
         'margin_new': fields.function(_get_margin_new,digits_compute=dp.get_precision('Account'),
                 string='销售毛利',readonly=True,
                 store={                                        
                        'sale.order': (lambda self, cr, uid, ids, c={}: ids, ['order_line','pur_ret_tax_eval','other_cost_total'], 10),
                        'sale.order.line': (_get_order_line, ['margin'], 10),
                        'sale.order.cost': (_get_order_cost_line, ['local_cost'], 10),
                        },
                ),
         'pur_ret_tax_eval': fields.function(_calc_ret_tax_eval, digits_compute=dp.get_precision('Account'), 
                 string='采购退税预估',readonly=True, help="The exporting return value evaluation.",
                 store={
                        'sale.order': (lambda self, cr, uid, ids, c={}: ids, ['order_line','is_normal_export'], 10),
                        },
                ),
         'other_cost_total': fields.function(_sum_other_cost, digits_compute=dp.get_precision('Account'), 
                 string='Total', help="The total other cost.",
                 store={
                        'sale.order.cost': (_get_order_cost_line, ['local_cost'], 10),
                        },
                ),
         'cost_line': fields.one2many('sale.order.cost', 'order_id', 'Other Cost', readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}),
         'date_due': fields.date('预计销售日期'),
         'box_marks': fields.char('唛头',size=64),
         'pack_method': fields.char('包装方式',size=64),
         'is_normal_export': fields.boolean('是否正式报关'),
         'is_print_signature': fields.boolean("Print Signature?"),
         'is_print_payinfo': fields.boolean("Print Pay Info?"),
         'local_currency_id': fields.related('company_id','currency_id',type='many2one',relation='res.currency', string='Local Currency',readonly=True),
    }

    _defaults = {
        'local_currency_id': lambda self, cr, uid, context: self.pool.get('res.users').browse(cr, uid, uid).company_id.currency_id.id,
        'box_marks':'Not Specified',
        'pack_method':'Normal Corrugated Carton Packing for International Shipment.'
    }      
    def _update_curr_date(self,cr,uid,ids,vals,context=None):
        so = None
        if(ids and len(ids) > 0): so = self.browse(cr, uid, ids, context)[0]
        pricelist_id = vals.get('pricelist_id') or (so and so.pricelist_id.id)
        curr_rate_quote = vals.get('curr_rate_quote') or (so and so.curr_rate_quote) or 0
        if curr_rate_quote <=0 : return
        date_order = vals.get('date_order') or so.date_order
        currency_id = self.pool.get('product.pricelist').browse(cr, uid, pricelist_id, context).currency_id.id
        if currency_id:
            res_curr_rate = self.pool.get("res.currency.rate")
            #Price List Currency Rate
            rate_ids = res_curr_rate.search(cr,uid,[('currency_id','=',currency_id),('name','=',date_order)])
            if(rate_ids and len(rate_ids) > 0):
                res_curr_rate.write(cr,uid,rate_ids,{'rate':curr_rate_quote},context)
            else:
                rate_vals={'currency_id':currency_id,'name':date_order,'rate':curr_rate_quote}
                res_curr_rate.create(cr,uid,rate_vals,context)    
            #get user's company currency as the local currency
            currency_id = self.pool.get('res.users').browse(cr, uid, uid).company_id.currency_id.id
            rate_ids = res_curr_rate.search(cr,uid,[('currency_id','=',currency_id),('name','=',date_order)])
            if(not rate_ids or len(rate_ids) <= 0):
                rate_vals={'currency_id':currency_id,'name':date_order,'rate':1}
                res_curr_rate.create(cr,uid,rate_vals,context)   
            
    def create(self, cr, uid, vals, context=None):
        #logic from addons.sale.sale.py
        if vals.get('name','/')=='/':
            vals['name'] = self.pool.get('ir.sequence').get(cr, uid, 'sale.order') or '/'
        #new logic, save the curr_rate_quote and curr_rate_confirm
        self._update_curr_date(cr,uid,[],vals,context);
        return super(sale_order, self).create(cr, uid, vals, context=context)  
       
    def write(self, cr, uid, ids, vals, context=None):
        #new logic, save the curr_rate_quote and curr_rate_confirm
        self._update_curr_date(cr,uid,ids,vals,context)
        return super(sale_order,self).write(cr, uid, ids, vals, context)  
    
    def onchange_pricelist_id(self, cr, uid, ids, pricelist_id, order_lines, date_order, context=None):
        ret_info = super(sale_order, self).onchange_pricelist_id(cr, uid, ids, pricelist_id, order_lines, context)
        ret_value = ret_info.get('value')
        if ret_value and ret_value.get('currency_id'):
            #get user's company currency as the from currency
            from_curr = self.pool.get('res.users').browse(cr, uid, uid).company_id.currency_id
            res_curr = self.pool.get("res.currency")
            to_curr = res_curr.browse(cr,uid,ret_value.get('currency_id'))
            curr_context={'date':date_order}
            ret_value.update({'curr_rate_quote':res_curr._get_conversion_rate(cr,uid,from_curr,to_curr,curr_context),
                              'local_currency_id':from_curr.id})
        return ret_info
             
    def print_quotation(self, cr, uid, ids, context=None):
        '''
        This function prints the sales order and mark it as sent, so that we can see more easily the next step of the workflow
        '''
        assert len(ids) == 1, 'This option should only be used for a single id at a time'
        wf_service = netsvc.LocalService("workflow")
        wf_service.trg_validate(uid, 'sale.order', ids[0], 'quotation_sent', cr)
        datas = {
                 'model': 'sale.order',
                 'ids': ids,
                 'form': self.read(cr, uid, ids[0], context=context),
        }
        return {'type': 'ir.actions.report.xml', 'report_name': 'sale.order.lijin', 'datas': datas, 'nodestroy': True}
    def action_button_confirm(self, cr, uid, ids, context=None):
        so = self.browse(cr, uid, ids[0], context)
        curr_rate_confirm = so.curr_rate_confirm or 0.0
        if curr_rate_confirm <= 0:
            raise osv.except_osv(_('No Confirmation Currency Rate Defined !'), _('Before confirm sale order,\n Confirmation Currency Rate must be set.'))
            return False
        return super(sale_order,self).action_button_confirm(cr,uid,ids,context)

class sale_order_line(osv.osv):
    _inherit = 'sale.order.line'
    _columns = {
    'name': fields.text('Description', required=True, readonly=True, states={'draft': [('readonly', False)]}, translate=True),
    }
                             
class sale_order_line_lijin(warning.warning.sale_order_line):
    def product_id_change(self, cr, uid, ids, pricelist, product, qty=0,
            uom=False, qty_uos=0, uos=False, name='', partner_id=False,
            lang=False, update_tax=True, date_order=False, packaging=False, fiscal_position=False, flag=False, 
            curr_rate_quote=False, context=None):
        if context is None:
                    context = {}  
        if not  curr_rate_quote or curr_rate_quote <= 0:
            raise osv.except_osv(_('No Quotation Currency Rate Defined !'), _('Before choosing a product,\n Quotation Currency Rate must be set.'))
        else:
            so = self.pool.get("sale.order")   
            so_vals = {'pricelist_id':pricelist,'curr_rate_quote':curr_rate_quote,'date_order':date_order}
            so._update_curr_date(cr,uid,[],so_vals,context)                         
        product_vals = super(sale_order_line_lijin,self).product_id_change(
                            cr, uid, ids, pricelist, product, qty,
                            uom, qty_uos, uos, name, partner_id,
                            lang, update_tax, date_order, packaging, fiscal_position, flag, context)
        product_obj = None
        if product:
            partner_id = context.get("partner_id")
            partner_lang = self.pool.get('res.partner').read(cr,uid,partner_id,['lang'])['lang']
            product_obj = self.pool.get('product.product').browse(cr, uid, product,context={'lang':partner_lang})   
            #update the 'name' to product description       
            product_vals['value'].update({'name':product_obj.description })     
        #fix the bug that won't use data_order as the currency rate date, 
        #on sale_margin.py product_id_change() computing the purchase_price
        if not pricelist:
            return product_vals
        frm_cur = self.pool.get('res.users').browse(cr, uid, uid).company_id.currency_id.id
        to_cur = self.pool.get('product.pricelist').browse(cr, uid, [pricelist])[0].currency_id.id
        if product:
            purchase_price = product_obj.standard_price
            context = context or {}
            context.update({'date':date_order})
            price = self.pool.get('res.currency').compute(cr, uid, frm_cur, to_cur, purchase_price, round=False,context=context)
            product_vals['value'].update({'purchase_price': price})     
        return product_vals
    def product_uom_change(self, cursor, user, ids, pricelist, product, qty=0,
            uom=False, qty_uos=0, uos=False, name='', partner_id=False,
            lang=False, update_tax=True, date_order=False, curr_rate_quote=False, context=None):
        context = context or {}
        lang = lang or ('lang' in context and context['lang'])
        if not uom:
            return {'value': {'price_unit': 0.0, 'product_uom' : uom or False}}
        return self.product_id_change(cursor, user, ids, pricelist, product,
                qty=qty, uom=uom, qty_uos=qty_uos, uos=uos, name=name,
                partner_id=partner_id, lang=lang, update_tax=update_tax,
                date_order=date_order, curr_rate_quote=curr_rate_quote, context=context)
#sale cost items in the 'Other Cost' tabs            
class sale_order_cost(osv.osv): 
    _name = "sale.order.cost"
    _description = 'Sale costs that user entered manually'
    _columns = {
        'order_id': fields.many2one('sale.order', 'Order Reference', required=True, ondelete='cascade', select=True, readonly=True, states={'draft':[('readonly',False)]}),
        'name': fields.char(string='Name', size=64, required=True),
        'local_currency_id': fields.many2one('res.currency','Local Currency',required=True),
        'local_cost':fields.float('Cost by Local Currency', digits=(16,2), required=True),
        'foreign_currency_id':fields.many2one('res.currency','Foreign Currency'),
        'foreign_cost':fields.float('Cost in Foreign Currency', digits=(16,2)),
        'currency_rate':fields.float('Currency Rate',digits=(12,6)),
        'memo':fields.text('Description'),
    }
    def default_get(self, cr, uid, fields_list, context=None):
        vals = super(sale_order_cost,self).default_get(cr, uid, fields_list, context)
        if not context.get('sale_currency_id'): return vals
        vals.update({
                     'local_currency_id':self.pool.get('res.users').browse(cr, uid, uid).company_id.currency_id.id,
                     'foreign_currency_id':context.get('sale_currency_id'),
                     'currency_rate':context.get('curr_rate_quote'),
                     })
        return vals
#    def cost_change(self, cr, uid, ids, cost_field, cost_new, currency_rate, context=None):
#        vals = {}
#        if not hasattr(self, 'context'): 
#            self.context = {}
#        elif self.context.get("cost_change"):
#            self.context.update({'cost_change':False})
#            return {'value': {cost_field:cost_new}}
#        
#        if(cost_field == 'local' or cost_field == 'currency_rate'): 
#            foreign_cost = cost_new * currency_rate
#            vals['foreign_cost'] = foreign_cost
#            self.context.update({'foreign_cost':vals['foreign_cost']})
#            if foreign_cost > 0 : self.context.update({'cost_change':True})
#        if(cost_field == 'foreign' and currency_rate != 0): 
#            local_cost = cost_new / currency_rate
#            vals['local_cost'] = local_cost
#            self.context.update({'local_cost':local_cost})
#            if local_cost > 0 : self.context.update({'cost_change':True})
#        return {'value': vals}
    def local_cost_change(self, cr, uid, ids, local_cost, currency_rate, context=None):
        if local_cost == 0: return {}
        vals = {}
        foreign_cost = local_cost * currency_rate
        vals['foreign_cost'] = float('%.2f' %foreign_cost)
        return {'value': vals}  
    def currency_rate_change(self, cr, uid, ids, local_cost, currency_rate, context=None):
        return self.local_cost_change( cr, uid, ids, local_cost, currency_rate, context)   
    def foreign_cost_change(self, cr, uid, ids, foreign_cost, currency_rate, context=None):
        if foreign_cost == 0: return {}
        vals = {}
        if currency_rate != 0: local_cost = foreign_cost / currency_rate
        vals['local_cost'] = float('%.2f' %local_cost)
        return {'value': vals}         
    def create(self, cr, uid, vals, context=None):
        return super(sale_order_cost, self).create(cr, uid, vals, context=context)  
       
    def write(self, cr, uid, ids, vals, context=None):
        return super(sale_order_cost,self).write(cr, uid, ids, vals, context)   
       
#redefine the sale PDF report to new rml
from openerp.addons.sale.report.sale_order import order
from openerp.report import report_sxw

class sale_order_printer(order):
    def __init__(self, cr, uid, name, context):
        super(order, self).__init__(cr, uid, name, context=context)
        self.localcontext.update({'get_main_contacter':self._get_main_contacter,
                                  'repeatIn':self.repeatIn,
                                  'get_ship_route':self._get_ship_route,
                                  'get_ship_method':self.get_ship_method,
                                  'get_picking_policy':self.get_picking_policy,
                                  'get_payinfo':self.get_payinfo,
                                  'get_frt_pay':self.get_frt_pay,
                                  'print_flag':self.get_print_flag,
                                  'partner_name':self.get_partner_name,
                                  'uom_digits':self.get_uom_digits
                                  })
    #get the main contacer name/phone/mobile             
    def _get_main_contacter(self,partner):
        res_partner = self.pool.get('res.partner');
        contacter_id = res_partner.search(self.cr,self.uid,[('parent_id', '=', partner.id),('is_main_contact', '=', True)],limit=1)
        if len(contacter_id) == 0: return ""
        contacter = res_partner.browse(self.cr,self.uid,contacter_id[0])
        return contacter.name
    def _get_ship_route(self,ship_method,load_port,discharge_port):
        route = ''
        if(ship_method == 'air' or ship_method == 'ocean'):
            route = 'from ' + load_port + ' to ' + discharge_port
        return route
    #add the idx(1...n) to the repeatIn() iteration objects in PDF
    def repeatIn(self, lst, name,nodes_parent=False):
        ret_lst = super(sale_order_printer,self).repeatIn(lst, name,nodes_parent)
        i = 0
        for obj in ret_lst:
            i = i + 1
            obj.get(name).idx = i
        return ret_lst 
    def get_ship_method(self,ship_method):
        return self._get_sellection_name('sale.order','ship_method',ship_method)
    def get_picking_policy(self,picking_policy):
        if picking_policy == 'direct':
            return 'Yes'
        else:
            return "No"
    #get the selection display value by the selection key(field_value)
    def _get_sellection_name(self,model_name,field_name,field_value):
#        context = {'lang':self.localcontext['lang']}
#        sel = self.pool.get(model_name).fields_get(self.cr,self.uid,[field_name],context=context)
#        selection = sel[field_name]['selection']
#        select_dict = {}
#        ret_result = ''
#        for sel_item in selection:
#            if(sel_item[0] == field_value):
#                ret_result = sel_item[1]
#                break
#        print ret_result
#        return ret_result
        field_sel = self.pool.get(model_name)._columns[field_name].selection
        trans_src = field_value;
        for sel_item in field_sel:
            if(sel_item[0] == field_value):
                trans_src = sel_item[1]
                break
        trans_obj = self.pool.get('ir.translation')
        trans_name = model_name + ',' + field_name
        trans_result = trans_obj._get_source(self.cr, self.uid, trans_name, 'selection', self.localcontext.get('lang'), trans_src)
        return trans_result
    #get the payment info pringted in PDF
    def get_payinfo(self,pay_account):
        flds = self.pool.get('res.pay.account').fields_get(self.cr, self.uid, context={'lang':self.localcontext.get('lang')})
        resu = ''
        if pay_account.pay_method == 'pay_method_tt':
            resu = flds['tt_person']['string'] + ':' + (pay_account.tt_person or '') + '\n' + \
                    flds['tt_addr']['string'] + ':' + (pay_account.tt_addr or '') + '\n' + \
                    flds['tt_bank_account']['string'] + ':' + (pay_account.tt_bank_account or '') + '\n' + \
                    flds['tt_bank_name']['string'] + ':' + (pay_account.tt_bank_name or '') + '\n' + \
                    flds['tt_bank_addr']['string'] + ':' + (pay_account.tt_bank_addr or '') + '\n' + \
                    flds['tt_bank_swift']['string'] + ':' + (pay_account.tt_bank_swift or '')
        if pay_account.pay_method == 'pay_method_paypal':
            resu = flds['paypal_email']['string'] + ':' + (pay_account.paypal_email or '')    
        if pay_account.pay_method == 'pay_method_wu':
            resu = flds['wu_first_name']['string'] + ':' + (pay_account.wu_first_name or '') + '\n' + \
                    flds['wu_last_name']['string'] + ':' + (pay_account.wu_last_name or '') + '\n' + \
                    flds['wu_iden_no']['string'] + ':' + (pay_account.wu_iden_no or '') + '\n' + \
                    flds['wu_addr']['string'] + ':' + (pay_account.wu_addr or '') + '\n' + \
                    flds['wu_tel']['string'] + ':' + (pay_account.wu_tel or '') + '\n'
        if pay_account.pay_method == 'pay_method_dap':
            resu = flds['dap_memo']['string'] + ':' + (pay_account.dap_memo or '')   
        if pay_account.pay_method == 'pay_method_loc':
            resu = flds['loc_memo']['string'] + ':' + (pay_account.loc_memo or '')                            
        return resu

    def get_frt_pay(self,frt_pay_method):
        pay_name = ''
        for obj in frt_pay_method:
            pay_name += obj.name + ', ' 
        if pay_name != '': 
            pay_name = pay_name[0:(len(pay_name)-2)]
        return pay_name
    def get_print_flag(self,obj,flag_name=False):
        if not hasattr(self, 'print_flag_vals'):
            self.print_flag_vals = ({'marks':False,'ship_route':False,'pay_title':False})
            if obj.box_marks and obj.box_marks != '': 
                self.print_flag_vals.update({'marks':True})
            if(obj.ship_method == 'air' or obj.ship_method == 'ocean'): 
                self.print_flag_vals.update({'ship_route':True})
            if(obj.res_pay_account_id.pay_method == 'pay_method_tt' or obj.res_pay_account_id.pay_method == 'pay_method_loc') :
                self.print_flag_vals.update({'pay_title':True})
        if not flag_name: 
            return self.print_flag_vals
        else:
            return self.print_flag_vals.get(flag_name)
    def get_partner_name(self,partner_id):
        vals = self.pool.get('res.partner').read(self.cr,self.uid,partner_id,['name'],context=self.localcontext)
        return vals['name']
    
report_sxw.report_sxw('report.sale.order.lijin', 'sale.order', 'addons/lijin/report/sale_order.rml', parser=sale_order_printer, header="external")


#enhanced the workflow validate 
from openerp.workflow import instance
def trg_validate(self, uid, res_type, res_id, signal, cr):
    #added the purchase and sale order checking when do printing and confirmation
    #if the workflow instance exists, if not then create
    if (res_type == 'purchase.order' and (signal == 'send_rfq' or signal == 'purchase_confirm')) \
        or (res_type == 'sale.order' and (signal == 'quotation_sent' or signal == 'order_confirm')):  
        cr.execute('select id from wkf_instance where res_id=%s and res_type=%s', (res_id, res_type))
        if len(cr.fetchall()) == 0:
            self.trg_create(uid, res_type, res_id, cr)                       
    """
    Fire a signal on a given workflow instance

    :param res_type: the model name
    :param res_id: the model instance id the workflow belongs to
    :signal: the signal name to be fired
    :param cr: a database cursor
    """
    result = False
    ident = (uid,res_type,res_id)
    # ids of all active workflow instances for a corresponding resource (id, model_nam)
    cr.execute('select id from wkf_instance where res_id=%s and res_type=%s and state=%s', (res_id, res_type, 'active'))
    for (id,) in cr.fetchall():
        res2 = instance.validate(cr, id, ident, signal)
        result = result or res2
    return result
        
workflow_service.trg_validate = trg_validate   